package com.atom.dbflow

import android.Manifest
import android.os.Bundle
import android.os.Environment
import android.util.Log
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import androidx.annotation.MainThread
import androidx.appcompat.app.AppCompatActivity
import com.atom.other.DBFlowOtherDatabase
import com.raizlabs.android.dbflow.config.DBFlowDatabaseGeneratedDatabaseHolder
import com.raizlabs.android.dbflow.config.DBFlowOtherDatabaseGeneratedDatabaseHolder
import com.raizlabs.android.dbflow.config.FlowConfig
import com.raizlabs.android.dbflow.config.FlowManager
import com.raizlabs.android.dbflow.runtime.DirectModelNotifier
import com.raizlabs.android.dbflow.runtime.OnTableChangedListener
import com.raizlabs.android.dbflow.sql.language.SQLOperator
import com.raizlabs.android.dbflow.structure.BaseModel
import com.raizlabs.android.dbflow.structure.database.transaction.Transaction
import com.saop.annotation.AopIntercept
import com.saop.annotation.AopLog
import com.saop.annotation.AopPermissionVoid
import java.io.File
import java.util.*

class DBFlowActivity : AppCompatActivity() {

    companion object {
        @AopLog
        @AopIntercept(1)
        fun testSAOP(): Int {
            return 123
        }
    }

    private var userHelper: UserHelper = UserHelper()
    private var usermanHelper: UserManHelper = UserManHelper()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_dbflow)

        findViewById<Button>(R.id.init_db).setOnClickListener {
            createDb()
        }
        findViewById<Button>(R.id.recycle_db).setOnClickListener {
            recycleDb()
        }


        findViewById<Button>(R.id.db_insert).setOnClickListener {
            val input = findViewById<EditText>(R.id.input).text.toString()
            val apply = User().apply {
                this.id = (UUID.randomUUID().toString())
                this.name = ("主module $input + ${System.currentTimeMillis()}")
                this.updateAt = (Date(System.currentTimeMillis()))
            }

            usermanHelper.save(UserMan().apply {
                this.age = input
                this.updateAt = (Date(System.currentTimeMillis()))
            })

            userHelper.save(
                Collections.singleton(apply),
                Transaction.Success { t -> Log.e("DBFlowActivity", "保存成功") },
                Transaction.Error { transaction, error -> Log.e("DBFlowActivity", "保存失败") },
                true, false
            )
        }

        findViewById<Button>(R.id.db_insert_man).setOnClickListener {
            val input = findViewById<EditText>(R.id.input).text.toString()
            usermanHelper.save(UserMan().apply {
                this.age = input
                this.updateAt = (Date(System.currentTimeMillis()))
            })
        }

        findViewById<Button>(R.id.db_insert_async).setOnClickListener {
            val input = findViewById<EditText>(R.id.input).text.toString()
            val apply = User().apply {
                this.id = (UUID.randomUUID().toString())
                this.name = ("主module simple $input + ${System.currentTimeMillis()}")
                this.createAt = (Date(System.currentTimeMillis()))
                this.updateAt = (Date(System.currentTimeMillis()))
            }
            userHelper.save(Collections.singleton(apply),
                Transaction.Success { t -> Log.e("DBFlowActivity", "保存成功") },
                Transaction.Error { transaction, error -> Log.e("DBFlowActivity", "保存失败") }
            )
        }
        // 更新
        findViewById<Button>(R.id.db_update_simple).setOnClickListener {
            val toString = findViewById<EditText>(R.id.input_uuid).text.toString()
            val single = userHelper.getSingle(toString) ?: return@setOnClickListener
            userHelper.update(single.apply {
                this.updateAt = (Date(System.currentTimeMillis()))
            })
        }
        findViewById<Button>(R.id.db_update_all).setOnClickListener {
            val toString = findViewById<EditText>(R.id.input_uuid).text.toString()
            val single = userHelper.getSingle(toString) ?: return@setOnClickListener
            userHelper.update(Collections.singleton(single.apply {
                this.updateAt = (Date(System.currentTimeMillis()))
            }), Transaction.Success { t -> Log.e("DBFlowActivity", "更新成功") },
                Transaction.Error { t, e -> Log.e("DBFlowActivity", "更新失败") })
        }
        findViewById<Button>(R.id.db_update_callback).setOnClickListener {
            val toString = findViewById<EditText>(R.id.input_uuid).text.toString()
            val single = userHelper.getSingle(toString) ?: return@setOnClickListener
            userHelper.update(
                mutableListOf<SQLOperator>().apply {
                    add(User_Table.updateAt.eq(Date(System.currentTimeMillis())))
                },
                mutableListOf<SQLOperator>().apply {
                    add(User_Table.id.eq(single.id))
                },
                Transaction.Success { t -> Log.e("DBFlowActivity", "更新成功") },
                Transaction.Error { t, e -> Log.e("DBFlowActivity", "更新失败") })

        }
        findViewById<Button>(R.id.db_update_sync).setOnClickListener {
            val toString = findViewById<EditText>(R.id.input_uuid).text.toString()
            val single = userHelper.getSingle(toString) ?: return@setOnClickListener
            val update = userHelper.update(
                mutableListOf<SQLOperator>().apply {
                    add(User_Table.updateAt.eq(Date(System.currentTimeMillis())))
                },
                mutableListOf<SQLOperator>().apply {
                    add(User_Table.id.eq(single.id))
                })
            Log.e("DBFlowActivity", "更新成功 $update")
        }
        // 删除
        findViewById<Button>(R.id.db_delete_simple).setOnClickListener {
            val toString = findViewById<EditText>(R.id.input_uuid).text.toString()
            val single = userHelper.getSingle(toString) ?: return@setOnClickListener
            userHelper.delete(single)
        }
        findViewById<Button>(R.id.db_delete_all).setOnClickListener {
            val toString = findViewById<EditText>(R.id.input_uuid).text.toString()
            val single = userHelper.getSingle(toString) ?: return@setOnClickListener
            userHelper.delete(Collections.singleton(single),
                Transaction.Success { t -> Log.e("DBFlowActivity", "删除成功") },
                Transaction.Error { t, e -> Log.e("DBFlowActivity", "删除失败") })
        }
        findViewById<Button>(R.id.db_delete_callback).setOnClickListener {
            val toString = findViewById<EditText>(R.id.input_uuid).text.toString()
            val single = userHelper.getSingle(toString) ?: return@setOnClickListener
            userHelper.delete(mutableListOf<SQLOperator>().apply {
                add(User_Table.id.eq(single.id))
            },
                Transaction.Success { t -> Log.e("DBFlowActivity", "删除成功") },
                Transaction.Error { t, e -> Log.e("DBFlowActivity", "删除失败") })
        }
        findViewById<Button>(R.id.db_delete_sync).setOnClickListener {
            val toString = findViewById<EditText>(R.id.input_uuid).text.toString()
            val single = userHelper.getSingle(toString) ?: return@setOnClickListener
            val delete = userHelper.delete(mutableListOf<SQLOperator>().apply {
                add(User_Table.id.eq(single.id))
            })
            Log.e("DBFlowActivity", "删除成功 $delete")
        }

        findViewById<Button>(R.id.db_query).setOnClickListener {
            val toString = findViewById<EditText>(R.id.input_uuid).text.toString()
            val single = userHelper.getSingle(toString) ?: return@setOnClickListener
            Log.e("DBFlowActivity", "query -> \n $single")
        }
    }

    @AopPermissionVoid(
        Manifest.permission.WRITE_EXTERNAL_STORAGE,
        Manifest.permission.READ_EXTERNAL_STORAGE
    )
    private fun createDb() {
        val input = findViewById<EditText>(R.id.input).text.toString()
        sdCardIsAvailable()?.also {
            FlowManager.init(
                FlowConfig.Builder(DBFlowContext.initDB(applicationContext, File(it, input)))
                    .addDatabaseHolder(DBFlowDatabaseGeneratedDatabaseHolder::class.java)
                    .addDatabaseHolder(DBFlowOtherDatabaseGeneratedDatabaseHolder::class.java)
                    .build()
            )
        }
        checkDB()
    }

    @MainThread
    private fun checkDB() {
        arrayListOf<String>().apply {
            this.add(DBFlowDatabase.NAME)
            this.add(DBFlowOtherDatabase.NAME)
        }.also {
            var ok = true
            it.forEach { name ->
                ok = ok and FlowManager.isDatabaseIntegrityOk(name)
            }
            findViewById<TextView>(R.id.msg).text = "检查结果是 $ok"
        }
    }

    @AopPermissionVoid(
        Manifest.permission.WRITE_EXTERNAL_STORAGE,
        Manifest.permission.READ_EXTERNAL_STORAGE
    )
    private fun recycleDb() {
        FlowManager.destroy()
    }

    fun sdCardIsAvailable(): File? {
        //首先判断外部存储是否可用
        return if (Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED) {
            File(Environment.getExternalStorageDirectory().path)
        } else {
            null
        }
    }
}